/*
 * @Author: 陈熠琳 1016598572@qq.com
 * @Date: 2023-07-24 04:29:54
 * @LastEditors: 陈熠琳 1016598572@qq.com
 * @LastEditTime: 2023-07-24 05:10:59
 * @FilePath: /rm_sentry_2023/src/driver_module/camera/hik/HikCamera.h
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once

#include <chrono>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <thread>

#include "CamBase.h"
#include "CameraParams.h"
#include "MvCameraControl.h"
namespace hitcrt
{
    namespace camera
    {
        class HikParams : public CameraParams
        {
        public:
            HikParams() = default;
            HikParams(const hitcrt::camera::CallBack &onCall, const int id, const Mode mode, const int _width,
                      const int _height, const int _ADCBitDepth, const float _exposureTime, const float _gain,
                      const int _blackLevel, const std::vector<int> &_balanceRatio = {},
                      const std::function<void(unsigned int)> &exceptionFunc = ignoreException,
                      const std::function<void()> &onGet = noUse, std::string _sn = "");
            ~HikParams() = default;

            void show() const;
            // set attrs:
            void set(const CallBack &onCall, const int id, const Mode mode, const int width, const int height,
                     const int ADCBitDepth, const float exposureTime, const float gain, const int blackLevel,
                     const std::vector<int> &balanceRatio,
                     const std::function<void(unsigned int type)> &exceptionFunc, const std::function<void()> &onGet=noUse,
                     std::string SN = "");
            static void noUse(){};
            static void ignoreException(unsigned int exception){};

        public:
            int width, height;  // 图像尺寸
            int ADCBitDepth;    // 0->8bit 3->12bit
            float exposureTime; // 曝光时间(abs)
            float gain;         // dB 0-16
            int blackLevel;
            std::string sn;
            std::vector<int> balanceRatio; // 白平衡增益RGB 1024为基准
            // callback functions
            std::function<void()> m_onGetCallback = noUse;                                // 抓图前处理回调
            std::function<void(unsigned int type)> m_exceptionCallback = ignoreException; // 离线回调
        };

        class HikCamera : public Camera
        {
        public:
            HikCamera() {}
            HikCamera(const HikParams &param);
            ~HikCamera() { terminate(); }

            bool initiate(const HikParams &param);

            bool set(const HikParams &param);

            bool restart(const HikParams &param);

            bool setParamsOnline(const HikParams &param);

            bool terminate();
            // get attr:
            HikParams getParam();

            bool isOpened();

        protected:
            using Context = std::tuple<HikCamera *>;

            // override
            bool findDevices() override;

            bool open(const uint id = 0) override;

            bool close() override;

            bool start(const CameraParams &param) override;

            bool stop(const CameraParams &param) override;

            // 运行函数
            bool retryConnect();

            bool setOperation(const HikParams &param);
            // callback
            static void frameCallbackAdapter(unsigned char *pData, MV_FRAME_OUT_INFO_EX *pFrameInfo, void *context);
            static void statusCallbackAdapter(unsigned int nMsgType, void *pUser);

            static void displayDeviceInfo(MV_CC_DEVICE_INFO *pstMVDevInfo);

            HikParams m_params;

            MV_CC_DEVICE_INFO_LIST m_deviceList;
            void *m_cameraHandle = nullptr;
            int m_cameraIndex;

            const int MAX_RETRY_TIMES = 10;
        };
    } // namespace camera
} // namespace hitcrt